package cn.line5.seam.component;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import cn.line5.seam.annotations.In;
import cn.line5.seam.annotations.Name;
import cn.line5.seam.annotations.Out;
import cn.line5.seam.annotations.Parameter;
import cn.line5.seam.annotations.Request;
import cn.line5.seam.cache.ComponentCache;
import cn.line5.seam.exception.SeamException;
import cn.line5.seam.intercept.BaseInterceptor;
import cn.line5.seam.util.ReflectUtil;

/**
 * <h1>组件类</h1>
 * 
 * @author Liu,Xiaojun
 * @since JDK1.6
 */
public class Component {
	private Class<?> clazz;

	private String name;

	private Map<String, In> inField = new HashMap<String, In>();

	private Map<String, Out> outField = new HashMap<String, Out>();

	private Map<String, Parameter> parameterField = new HashMap<String, Parameter>();
	
	private Map<String, Request> requestField = new HashMap<String, Request>();

	private Object component;

	/**
	 * 获取组件
	 * 
	 * @param name
	 *            组件名称
	 */
	public static Object geteInstance(String name) {
		if (ComponentCache.componentClass.containsKey(name)) {
			return ComponentCache.componentClass.get(name)
					.getComponentInterceptor();
		} else {
			throw new SeamException("Can't found component by named '" + name
					+ "'");
		}
	}

	/**
	 * 构造方法，如果class并不是定义的组件，将抛出异常。
	 * 
	 * @param clazz
	 *            组件的Class
	 */
	public Component(Class<?> clazz) {
		this.clazz = clazz;
		init();
	}

	private void init() {
		Name name = this.clazz.getAnnotation(Name.class);
		if (name != null) {
			this.name = name.value();
			Field[] fieldArray = clazz.getDeclaredFields();
			for (Field field : fieldArray) {
				In in = field.getAnnotation(In.class);
				Parameter parameter = field.getAnnotation(Parameter.class);
				Out out = field.getAnnotation(Out.class);
				Request request = field.getAnnotation(Request.class);
				if (in != null)
					inField.put(field.getName(), in);
				if (out != null)
					outField.put(field.getName(), out);
				if (parameter != null)
					parameterField.put(field.getName(), parameter);
				if (request != null)
					requestField.put(field.getName(), request);
			}
		}
	}

	/**
	 * 获取组件的Class
	 */
	public Class<?> getClazz() {
		return clazz;
	}

	/**
	 * 获取组件定义的组件名
	 */
	public String getName() {
		return name;
	}

	/**
	 * 获取组件的注入字段信息
	 */
	public Map<String, In> getInField() {
		return inField;
	}

	/**
	 * 获取组件输出字段信息
	 */
	public Map<String, Out> getOutField() {
		return outField;
	}

	/**
	 * 获取组件参数字段信息
	 */
	public Map<String, Parameter> getParameterField() {
		return parameterField;
	}
	
	/**
	 * 获取组件request对象信息
	 */
	public Map<String, Request> getRequestField() {
		return requestField;
	}

	/**
	 * 获取初始化的组件实体
	 */
	public Object getComponent() {
		if(ComponentCache.components.containsKey(this.name)){
			component = ComponentCache.components.get(this.name);
			// 清空输出
			if (outField != null && outField.size() > 0) {
				Iterator<Entry<String, Out>> t = outField.entrySet().iterator();
				while (t.hasNext())
					ReflectUtil.setFieldValue(t.next().getKey(), component, null);
			}
			// 清空参数
			if (parameterField != null && parameterField.size() > 0) {
				Iterator<Entry<String, Parameter>> t = parameterField.entrySet()
						.iterator();
				while (t.hasNext())
					ReflectUtil.setFieldValue(t.next().getKey(), component, null);
			}
			return component;
		}
		try {
			component = clazz.newInstance();
			ComponentCache.putComponent(name, component);
		} catch (Exception e) {
			throw new SeamException("The class '" + clazz.getName()
					+ "' instance error.", e);
		}
		if (inField != null && inField.size() > 0) {
			Iterator<Entry<String, In>> it = inField.entrySet().iterator();
			while (it.hasNext()) {
				Entry<String, In> entry = it.next();
				if (!ComponentCache.componentClass.containsKey(entry.getValue()
						.value())) {
					throw new SeamException(
							"Can't find the action class by named '"
									+ entry.getValue().value() + "'.");
				}
				ReflectUtil.setFieldValue(entry.getKey(), component,
						ComponentCache.componentClass.get(
						// entry.getValue().value()).getComponent());
								entry.getValue().value())
								.getComponentInterceptor());
			}
		}
		return component;
	}

	/**
	 * 获取拦截器机制的组件实体
	 */
	public Object getComponentInterceptor() {
		if(ComponentCache.interceptComponents.containsKey(name)){
			Object o = ComponentCache.interceptComponents.get(name);
			return o;
		}
		try {
			Object o = getComponent();
			ComponentCache.putInterceptComponent(name, o);
			o = BaseInterceptor.createCglibProxy(o);
			return o;
		} catch (Exception e) {
			throw new SeamException("The class '" + clazz.getName()
					+ "' instance error.", e);
		}
	}
}
